/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sle_address_parcel.h"
#include "sle_hilog.h"

namespace OHOS {
namespace NearLink {
namespace SleStandard {
SleAddress::SleAddress(const SleDeviceAddress &address)
{
    type_ = address.addrType;
    for(int i = 0; i < SLE_DEVICE_ADDRESS_LEN; i++) {
        address_[i] = address.addr[i];
    }
}

bool SleAddress::Marshalling(Parcel &parcel) const
{
    if(!parcel.WriteUint8(type_)) {
        return false;
    }
    for (size_t i = 0; i < SLE_DEVICE_ADDRESS_LEN; i++) {
        if(!parcel.WriteUint8(address_[i])) {
            return false;
        }
    }
    return true;
}

SleAddress *SleAddress::Unmarshalling(Parcel &parcel)
{
    SleAddress *address = new SleAddress();
    if (address != nullptr && !address->ReadFromParcel(parcel)) {
        delete address;
        address = nullptr;
    }
    return address;
}

bool SleAddress::ReadFromParcel(Parcel &parcel)
{
    if (!parcel.ReadUint8(type_)) {
        return false;
    }
    for (size_t i = 0; i < SLE_DEVICE_ADDRESS_LEN; i++) {
        if (!parcel.ReadUint8(address_[i])) {
            return false;
        }
    }
    return true;
}

SleDeviceAddress SleAddress::ConvertToSleDeviceAddress() const
{
    SleDeviceAddress address;
    address.addrType = (SleDevAddrType)type_;
    for(int i = 0; i < SLE_DEVICE_ADDRESS_LEN; i++) {
        address.addr[i] = address_[i];
    }
    return address;
}

SleErrorCode SleAddress::CheckSleAddress(const SleDeviceAddress &address)
{
    if (address.addrType != SLE_PUBLIC_ADDRESS_TYPE && address.addrType != SLE_RANDOM_ADDRESS_TYPE) {
        SLE_LOGE("check address type error!");
        return SLE_ERR_INVALID_PARAM;
    }
    bool AllZero = true;
    bool AllFF = true;
    for (int i = 0; i < SLE_DEVICE_ADDRESS_LEN; ++i) {
        if (address.addr[i] != 0x00) {
            AllZero = false;
        }
        if (address.addr[i] != 0xFF) {
            AllFF = false;
        }
    }
    SLE_ASSERT_AND_RETURN_RET_LOG((!AllZero && !AllFF), SLE_ERR_INVALID_PARAM, "check address error!");
    return SLE_NO_ERROR;
}

void SleAddress::GetRandomAddress(uint8_t address[SLE_DEVICE_ADDRESS_LEN])
{
    std::random_device rd;
    std::default_random_engine re(rd());
    std::uniform_int_distribution<int> random_value(0, 255);
    for (int i = 0; i < SLE_DEVICE_ADDRESS_LEN; ++i) {
        address[i] = static_cast<uint8_t>(random_value(re));
    }
}
} // SleStandard
} // NearLink
} // OHOS